Skip to content

1. 整合Servlet

方式一 注解扫描

编写servlet

xml
<servlet> 
    <servlet-name>FirstServlet</servlet-name> 
    <servlet-class>com.bjsxt.servlet.FirstServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>FirstServlet</servlet-name> 
    <url-pattern>/first</url-pattern>
</servlet-mapping>

代码

java
@WebServlet(name="FirstServlet",urlPatterns="/first") 
public class FirstServlet extends HttpServlet { 
    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        // TODO Auto-generated method stub 
        super.doGet(req, resp); 
    }
}

编写启动类

java
/**
* SpringBoot 整合 Servlet 方式一 
* exclude 排除不使用数据源的自动配置,使用多数据源时需这样配置
**/ 
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@SpringBootApplication 
@ServletComponentScan //在 springBoot 启动时会扫描@WebServlet,并将该类实例化
public class App { 
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    } 
}

方式二 方法

编写Servlet

java
/**
*SpringBoot 整合 Servlet 方式二 
**/
public class SecondServlet extends HttpServlet {
    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
        System.out.println("SecondServlet.........."); 
    }
}

编写启动类

java
/**
* SpringBoot 整合 Servlet 方式二 
*
**/ 
@SpringBootApplication 
public class App2 {
    public static void main(String[] args) {
        SpringApplication.run(App2.class, args); 
    }
    @Bean 
    public ServletRegistrationBean getServletRegistrationBean(){ 
        ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet()); 
        bean.addUrlMappings("/second"); 
        return bean; 
    } 
}

2. 整合Filter

方式一 注解扫描

编写filter

java
/**
*SpringBoot 整合 Filter 方式一 
*<filter> 
* <filter-name>FirstFilter</filter-name> 
* <filter-class>com.bjsxt.filter.FirstFilter</filter-class> 
*</filter> 
*<filter-mapping> 
* <filter-name>FirstFilter</filter-name> 
* <url-pattern>/first</url-pattern> 
*</filter-mapping> */ //@WebFilter(filterName="FirstFilter",urlPatterns={"*.do","*.jsp"})
@WebFilter(filterName="FirstFilter",urlPatterns="/first")
public class FirstFilter implements Filter { 
    @Override 
    public void destroy() {
        // TODO Auto-generated method stub 
    }
    @Override 
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { 
        System.out.println("进入 Filter");
        arg2.doFilter(arg0, arg1);
        System.out.println("离开 Filter");
    }
    @Override 
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub 
    } 
}

编写启动类

java
/**
*SpringBoot 整合 Filter 方式一 
**/
@SpringBootApplication
@ServletComponentScan 
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args); 
    } 
}

方式二 方法

编写Filter

java
/**
*
*SpringBoot 整合 Filter 方式二 
**/ 
public class SecondFilter implements Filter { 
    @Override 
    public void destroy() {
        // TODO Auto-generated method stub 
    }
    @Override 
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { 
        System.out.println("进入 SecondFilter");
        arg2.doFilter(arg0, arg1); 
        System.out.println("离开 SecondFilter"); 
    }
    @Override 
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub 
    } 
}

编写启动类

java
/**
* SpringBoot 整合 Filter 方式二 
*
**/ 
@SpringBootApplication 
public class App2 {
    public static void main(String[] args) {
        SpringApplication.run(App2.class, args); 
    }
    /**
    * 注册 Servlet 
    * @return 
    */
    @Bean public ServletRegistrationBean getServletRegistrationBean(){ 
        ServletRegistrationBean bean = new ServletRegistrationBean(new SecondServlet()); 
        bean.addUrlMappings("/second"); 
        return bean; 
    }
    /**
    * 注册 Filter 
    */ 
    @Bean 
    public FilterRegistrationBean getFilterRegistrationBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean(new SecondFilter());
        //bean.addUrlPatterns(new String[]{"*.do","*.jsp"});
        bean.addUrlPatterns("/second"); 
        return bean;
    } 
}

3. 整合Listener

方式一 注解

  1. 编辑Listener
    java
    /**
    * springBoot 整合 Listener 
    *
    *<listener> 
    * <listener-class>com.bjsxt.listener.FirstListener</listener-class> 
    *</listener> 
    */ 
    @WebListener 
    public class FirstListener implements ServletContextListener { 
        @Override 
        public void contextDestroyed(ServletContextEvent arg0) { 
            // TODO Auto-generated method stub 
        }
        @Override 
        public void contextInitialized(ServletContextEvent arg0) {
            System.out.println("Listener...init......"); 
        } 
    }
  2. 编写启动类
    java
    /**
    * springBoot 整合 Listener 方式一 
    *
    **/ 
    @SpringBootApplication 
    @ServletComponentScan 
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        } 
    }

方式二 方法

  1. 编写Listener
    java
    /**
    * springBoot 整合 Listener 方式二。 
    *
    **/
    public class SecondListener implements ServletContextListener { 
        @Override 
        public void contextDestroyed(ServletContextEvent arg0) { 
            // TODO Auto-generated method stub 
        }
        @Override 
        public void contextInitialized(ServletContextEvent arg0) {
            System.out.println("SecondListener..init....."); 
        } 
    }
  2. 编写启动类
    java
    /**
    * SpringBoot 整合 Listener 方式二
    *
    **/ 
    @SpringBootApplication 
    public class App2 {
        public static void main(String[] args) {
            SpringApplication.run(App2.class, args);
        }
        /**
        * 注册 listener 
        */ 
        @Bean 
        public ServletListenerRegistrationBean<SecondListener> getServletListenerRegistrationBean(){
            ServletListenerRegistrationBean<SecondListener> bean= new ServletListenerRegistrationBean<SecondListener>(new SecondListener());
            return bean; 
        }
    }

4. 整合视图层

4.1 整合jsp

依赖

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <parent> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-parent</artifactId> 
        <version>1.5.10.RELEASE</version> 
    </parent> 
    <groupId>com.bjsxt</groupId> 
    <artifactId>08-spring-boot-view-jsp</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <!-- jdk1.7 --> 
    <properties> 
        <java.version>1.7</java.version> 
    </properties> 
    <dependencies> 
        <!-- springBoot 的启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency> 
        <!-- jstl --> 
        <dependency> 
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId> 
        </dependency> 
        <!-- jasper --> 
        <dependency> 
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId> 
            <scope>provided</scope> 
        </dependency> 
    </dependencies> 
</project>

在application.properties中配置

properties
spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp

controller层

java
/**
* SpringBoot 整合 jsp 
*
**/
@Controller 
public class UserController {
    /** 处理请求,产生数据 */ 
    @RequestMapping("/showUser") 
    public String showUser(Model model){
        List<Users> list = new ArrayList<>();
        list.add(new Users(1,"张三",20)); 
        list.add(new Users(2,"李四",22)); 
        list.add(new Users(3,"王五",24));
        //需要一个 Model 对象
        model.addAttribute("list", list);
        //跳转视图
        return "userList";
    }
}
//调转jsp页面可从jsp页面中获取list对象。启动通过springboot启动类启动

4.2 整合Freemarker

pom依赖

xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <parent> 
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId> 
        <version>1.5.10.RELEASE</version> 
    </parent> 
    <groupId>com.bjsxt</groupId>
    <artifactId>09-spring-boot-view-freemarker</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <properties> 
        <java.version>1.7</java.version> 
    </properties> 
    <dependencies> 
        <!-- springBoot 的启动器 -->
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-web</artifactId> 
        </dependency> 
        <!-- freemarker 启动器的坐标 --> 
        <dependency> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-freemarker</artifactId> 
        </dependency> 
    </dependencies> 
</project>
  1. 编写视图
  • 数据同jsp一样通过model封装
  • springBoot 要求模板形式的视图层技术的文件必须要放到 src/main/resources目录下必 须要一个名称为 templates
    • 同下thymeleaf一样
  1. 配置
properties
spring.freemarker.allow-request-override=false
spring.freemarker.allow-session-override=false
spring.freemarker.cache=true
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.enabled=true  
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=true
spring.freemarker.prefer-file-system-access=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.settings.template_update_delay=0
spring.freemarker.settings.default_encoding=UTF-8
spring.freemarker.settings.classic_compatible=true 
spring.freemarker.order=1

4.3 整合Thymeleaf

  1. 添加pom依赖
    xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId> 
            <version>1.5.10.RELEASE</version> 
        </parent> 
        <groupId>com.bjsxt</groupId> 
        <artifactId>10-spring-boot-view-thymeleaf</artifactId>
        <version>0.0.1-SNAPSHOT</version> 
        <properties> 
            <java.version>1.7</java.version> 
            <!--  出现异常时升级版本或严谨html语法
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> 
    <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.versi on> -->
        </properties>
        <dependencies> 
            <!-- springBoot 的启动器 --> 
            <dependency> 
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency> 
            <!-- springBoot 的启动器 --> 
            <dependency> 
                <groupId>org.springframework.boot</groupId> 
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency> 
        </dependencies> 
    </project>

5. 整合MVC

  1. pom依赖

    xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> 
        <parent> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.10.RELEASE</version> 
        </parent> 
        <groupId>com.bjsxt</groupId> 
        <artifactId>12-spring-boot-springmvc-mybatis</artifactId> 
        <version>0.0.1-SNAPSHOT</version>
        <properties>
            <java.version>1.7</java.version> 
            <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version> 
            <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version> 
        </properties> 
        <dependencies> 
            <!-- springBoot 的启动器 -->
            <dependency> 
                <groupId>org.springframework.boot</groupId> 
                <artifactId>spring-boot-starter-web</artifactId> 
            </dependency> 
            <!-- web 启动器 --> 
            <dependency> 
                <groupId>org.springframework.boot</groupId> 
                <artifactId>spring-boot-starter-thymeleaf</artifactId> 
            </dependency> 
            <!-- Mybatis 启动器 -->
            <dependency> 
                <groupId>org.mybatis.spring.boot</groupId> 
                <artifactId>mybatis-spring-boot-starter</artifactId> 
                <version>1.1.1</version>
            </dependency> 
            <!-- mysql 数据库驱动 --> 
            <dependency> 
                <groupId>mysql</groupId> 
                <artifactId>mysql-connector-java</artifactId> 
            </dependency> 
            <!-- druid 数据库连接池 -->
            <dependency> <
                groupId>com.alibaba</groupId> 
                <artifactId>druid</artifactId> 
                <version>1.0.9</version>
            </dependency>
        </dependencies> 
    </project>
  2. 配置文件

properties
spring.datasource.driverClassName=com.mysql.jdbc.Driver 
spring.datasource.url=jdbc:mysql://localhost:3306/ssm 
spring.datasource.username=root 
spring.datasource.password=root 
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 
mybatis.type-aliases-package=com.bjsxt.pojo
  1. 编写代码和启动类
java
@SpringBootApplication 
@MapperScan("com.bjsxt.mapper") //@MapperScan 用户扫描MyBatis的Mapper接口
public class App { 
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    } 
}

6. 集成表单数据校验

SpringBoot 中使用了 Hibernate-validate 校验框架 依赖

xml
<!--1.导入JSR303规范-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<!--使用hibernate框架提供的校验器做实现-->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

注解含义

java
//在实体类中添加校验规则
@NotBlank: 判断字符串是否为 null 或者是空串(去掉首尾空格)。 
@NotEmpty: 判断字符串是否 null 或者是空串。
@Length: 判断字符的长度(最大或者最小)
@Min: 判断数值最小值 
@Max: 判断数值最大值 
@Email: 判断邮箱是否合法
private String name;

//在 Controller 中开启校验
public String saveUser(@Valid Users users,BindingResult result)

解决数据校验时的异常问题

java
/** 
* 解决异常的方式。可以在跳转页面的方法中注入一个 Uesrs 对象。 
* 注意:由于 springmvc 会将该对象放入到 Model 中传递。key 的名称会使用 该对象的驼峰式的命名规则来作为 key。 
* 参数的变量名需要与对象的名称相同。将首字母小写。 
*如果想为传递的对象更改名称,可以使用@ModelAttribute("aa")这表示当 前传递的对象的 key 为 aa
* @param users 
* @return 
*/ 
@RequestMapping("/addUser") 
public String showPage( @ModelAttribute("aa") Users users){ 
    return "add";
}

/** 
* 完成用户添加 
*@Valid 开启对 Users 对象的数据校验 
*BindingResult:封装了校验的结果 
*/
@RequestMapping("/save")
public String saveUser( @Valid Users users,BindingResult result){
    if(result.hasErrors()){
        return "add";
    }
    System.out.println(users);
    return "ok";
}

7. Junit单元测试

  1. pom依赖
xml
<!-- 添加 junit 环境的 jar 包 --> 
<dependency> 
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId> 
</dependency>
  1. 使用 SpringBoot 整合 Junit 做单元测试
java
/**
* SpringBoot 测试类 
*@RunWith:启动器 
*SpringJUnit4ClassRunner.class:让 junit 与 spring 环境进行整合 
*
*@SpringBootTest(classes={App.class}) 1,当前类为 springBoot 的测试类 
*@SpringBootTest(classes={App.class}) 2,加载 SpringBoot 启动类。启动 springBoot 
*
*junit 与 spring 整合 @Contextconfiguartion("classpath:applicationContext.xml") 
*/ 
@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest(classes={App.class}) 
public class UserServiceTest {
    @Autowired 
    private UserServiceImpl userServiceImpl;
    @Test
    public void testAddUser(){ 
        this.userServiceImpl.addUser();
    } 
}

8. 热部署

方式一 springLoader插件

  1. pom添加插件配置
xml
<!-- springloader 插件 --> 
<build> 
    <plugins>
        <plugin> 
            <groupId>org.springframework.boot</groupId> 
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies> 
                <dependency> 
                    <groupId>org.springframework</groupId> 
                    <artifactId>springloaded</artifactId> 
                    <version>1.2.5.RELEASE</version> 
                </dependency> 
            </dependencies> 
        </plugin> 
    </plugins> 
</build>
  1. 使用maven命令启动 spring-boot:run缺陷 是 Java 代码做部署处理。但是对页面无能为力。 这种方式的缺点是Springloader热部署程序是在 系统后台以进程的形式来运行。需要手动关闭该进程

方式二 DevTools工具

SpringLoader:SpringLoader 在部署项目时使用的是热部署的方式。 DevTools:DevTools 在部署项目时使用的是重新部署的方式

xml
<!-- DevTools 的坐标 -->
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-devtools</artifactId> 
    <optional>true</optional> 
</dependency>

9. 整合缓存技术

9.1 整合Ehcache

添加pom文件

xml
<!-- Spring Boot 缓存支持启动器 -->
<dependency> 
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId> 
</dependency>
<!-- Ehcache 坐标 --> 
<dependency> 
    <groupId>net.sf.ehcache</groupId> 
    <artifactId>ehcache</artifactId>
</dependency>

添加配置文件

xml
<!--src/main/resources/ehcache.xml -->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 
    <diskStore path="java.io.tmpdir"/>
     <!--默认缓存策略 -->
    <!-- external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为false-->
    <!-- diskPersistent:是否启用磁盘持久化-->
    <!-- maxElementsInMemory:最大缓存数量-->
    <!-- overflowToDisk:超过最大缓存数量是否持久化到磁盘-->
    <!-- timeToIdleSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码-->
    <!-- timeToLiveSeconds:最大存活时间-->
    <!-- memoryStoreEvictionPolicy:缓存清除策略-->
    <defaultCache 
                  maxElementsInMemory="10000"
                  eternal="false" 
                  timeToIdleSeconds="120"
                  timeToLiveSeconds="120" 
                  maxElementsOnDisk="10000000"
                  diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/> 
    </defaultCache> 
    <!-- 自定义缓存策略 -->
    <cache name="users"
           maxElementsInMemory="10000" 
           eternal="false" 
           timeToIdleSeconds="120" 
           timeToLiveSeconds="120" 
           maxElementsOnDisk="10000000"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"> 
        <persistence strategy="localTempSwap"/> 
    </cache> 
</ehcache>

配置application.properties文件

properties
spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/ssm spring.datasource.username=root
spring.datasource.password=root spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.cache.ehcache.cofnig=ehcache.xml

启动类添加 @EnableCaching注解 在业务层使用 @Cacheable(value="name")即可对查询的数据进行缓存

注解

  • @Cacheable: 把方法的返回值添加到 Ehcache 中做缓存 Value 属性:指定一个 Ehcache 配置文件中的缓存策略,如果么有给定 value,name 则 表示使用默认的缓存策略。 Key 属性:给存储的值起个名称。在查询时如果有名称相同的,那么则知己从缓存中将 数据返回

  • @CacheEvict: 清除缓存

9.2 整合 Spring Data Redis

  1. 安装redis
  2. pom引入依赖
xml
<!-- Spring Data Redis 的启动器 --> 
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 编写配置类或配置文件 配置文件
yaml
spring:
  redis:
    host: localhost
    port: 6379
  cache:
    type: redis
    redis:
      use-key-prefix: false
      key-prefix: sms_
      cache-null-values: false
      time-to-live: 10s

配置类:

java
/**
* 完成对 Redis 的整合的一些配置
*
**/
@Configuration 
public class RedisConfig { 
    /**
    * 1.创建 JedisPoolConfig 对象。在该对象中完成一些链接池配置 
    **/ 
    @Bean 
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig config = new JedisPoolConfig(); 
        //最大空闲数 
        config.setMaxIdle(10); 
        //最小空闲数 
        config.setMinIdle(5);
        //最大链接数 
        config.setMaxTotal(20);
        return config;
    }
    /**
    * 2.创建 JedisConnectionFactory:配置 redis 链接信息 
    */
    @Bean 
    public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig config){
        JedisConnectionFactory factory = new JedisConnectionFactory();
        //关联链接池的配置对象
        factory.setPoolConfig(config); 
        //配置链接 Redis 的信息
        //主机地址 
        factory.setHostName("192.168.70.128"); 
        //端口 
        factory.setPort(6379);
        return factory;
    }
    /**
    * 3.创建 RedisTemplate:用于执行 Redis 操作的方法
    */
    @Bean 
    public RedisTemplate<String,Object> redisTemplate(JedisConnectionFactory factory){
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //关联 
        template.setConnectionFactory(factory); 
        //为 key 设置序列化器 
        template.setKeySerializer(new StringRedisSerializer());
        //为 value 设置序列化器 
        template.setValueSerializer(new StringRedisSerializer()); 
        return template; 
    } 
}
  1. 通过注入的 RedisTemplate<String, Object>存取值 可以通过设置不同的序列化器设置存储数据的格式
java
this.redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
//以json格式
this.redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Users.class));

调用类

java
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootJpaApplication.class)
public class RedisTest {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //从redis缓存中获得指定的数据
        String userListData = redisTemplate.boundValueOps("user.findAll").get();
        //如果redis中没有数据的话
        if(null==userListData){
            //查询数据库获得数据
            List<User> all = userRepository.findAll();
            //转换成json格式字符串
            ObjectMapper om = new ObjectMapper();
            userListData = om.writeValueAsString(all);
            //将数据存储到redis中,下次在查询直接从redis中获得数据,不用在查询数据库
            redisTemplate.boundValueOps("user.findAll").set(userListData);
            System.out.println("===============从数据库获得数据===============");
        }else{
            System.out.println("===============从redis缓存中获得数据===============");
        }

        System.out.println(userListData);

    }

}

9.3 内置缓存

依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

启用

java
@SpringBootApplication
//开启缓存功能
@EnableCaching
public class Springboot19CacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot19CacheApplication.class, args);
    }
}

使用示例

java
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;

    // value属性描述缓存的存储位置,可以理解为是一个存储空间名,key属性描述了缓存中保存数据的名称,使用#id读取形参中的id值作为缓存名称。
    // 如果缓存中没有,正常读取数据,放入缓存,如果缓存中有,直接返回。
    // @CachePut仅具有向缓存中保存数据的功能
    @Cacheable(value="cacheSpace",key="#id")
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }
}

9.4 整合Memcached缓存

由于memcached未被springboot收录为缓存解决方案,因此使用memcached需要通过手工硬编码的方式来使用,

memcached目前提供有三种客户端技术,分别是Memcached Client for Java、SpyMemcached和Xmemcached,其中性能指标各方面最好的客户端是Xmemcached 依赖

xml
<dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.7</version>
</dependency>

配置类

java
@Configuration
public class XMemcachedConfig {
    @Bean
    public MemcachedClient getMemcachedClient() throws IOException {
        MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
        MemcachedClient memcachedClient = memcachedClientBuilder.build();
        return memcachedClient;
    }
}

使用示例

java
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @Autowired
    private CodeUtils codeUtils;
    @Autowired
    private MemcachedClient memcachedClient;

    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        try {
            memcachedClient.set(tele,10,code);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
        String code = null;
        try {
            code = memcachedClient.get(smsCode.getTele()).toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return smsCode.getCode().equals(code);
    }
}

9.5 整合jetcache缓存

jetcache严格意义上来说,并不是一个缓存解决方案,只能说他算是一个缓存框架,然后把别的缓存放到jetcache中管理,可是使多个缓存共同使用。 目前jetcache支持的缓存方案本地缓存支持两种,远程缓存支持两种,分别如下:

  • 本地缓存(Local)LinkedHashMap、Caffeine
  • 远程缓存(Remote)Redis、Tair

以LinkedHashMap+Redis实现为例

纯远程方案

依赖

xml
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

配置

yaml
jetcache:
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig: # 必配项
        maxTotal: 50

启用

java
@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
public class Springboot20JetCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

使用示例

java
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @Autowired
    private CodeUtils codeUtils;
    
    // 注解可配置area,代表选择哪个缓存,默认是选择default,缓存可以配置多个,和default中配置相同。deafult是名称
    @CreateCache(name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
    private Cache<String ,String> jetCache;

    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}

纯本地方案

远程方案中,配置中使用remote表示远程,换成local就是本地,只不过类型不一样而已。 依赖

xml
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

配置

yaml
jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson # key转换器,加快匹配速度。

启用缓存

java
@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
public class Springboot20JetCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

使用示例

java
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
    private Cache<String ,String> jetCache;

    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}

本地+远程方案

配置

yaml
jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

使用

java
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.BOTH)
    private Cache<String ,String> jetCache;
}

cacheType如果不进行配置,默认值是REMOTE,即仅使用远程缓存方案。关于jetcache的配置,参考以下信息

属性默认值说明
jetcache.statIntervalMinutes0统计间隔,0表示不统计
jetcache.hiddenPackages自动生成name时,隐藏指定的包名前缀
jetcache.[local|remote].${area}.type缓存类型,本地支持linkedhashmap、caffeine,远程支持redis、tair
jetcache.[local|remote].${area}.keyConvertorkey转换器,当前仅支持fastjson
jetcache.[local|remote].${area}.valueEncoderjava仅remote类型的缓存需要指定,可选java和kryo
jetcache.[local|remote].${area}.valueDecoderjava仅remote类型的缓存需要指定,可选java和kryo
jetcache.[local|remote].${area}.limit100仅local类型的缓存需要指定,缓存实例最大元素数
jetcache.[local|remote].${area}.expireAfterWriteInMillis无穷大默认过期时间,毫秒单位
jetcache.local.${area}.expireAfterAccessInMillis0仅local类型的缓存有效,毫秒单位,最大不活动间隔

以上方案仅支持手工控制缓存,但是springcache方案中的方法缓存特别好用,给一个方法添加一个注解,方法就会自动使用缓存。jetcache也提供了对应的功能,即方法缓存。

方法缓存

依赖

xml
<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

配置

yaml
jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      keyConvertor: fastjson
      valueEncode: java
      valueDecode: java
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

由于redis缓存中不支持保存对象,因此需要对redis设置当Object类型数据进入到redis中时如何进行类型转换。需要配置keyConvertor表示key的类型转换方式,同时标注value的转换类型方式,值进入redis时是java类型,标注valueEncode为java,值从redis中读取时转换成java,标注valueDecode为java。

注意,为了实现Object类型的值进出redis,需要保障进出redis的Object类型的数据必须实现序列化接口。

开启缓存

java
@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
//开启方法注解缓存
@EnableMethodCache(basePackages = "com.itheima")
public class Springboot20JetCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

使用

java
@Service
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;
    
    @Override
    @Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
    public Book getById(Integer id) {
        return bookDao.selectById(id);
    }
}

数据同步

由于远程方案中redis保存的数据可以被多个客户端共享,这就存在了数据同步问题。jetcache提供了3个注解解决此问题,分别在更新、删除操作时同步缓存数据,和读取缓存时定时刷新数据 缓存操作

java
//更新缓存
@CacheUpdate(name="book_",key="#book.id",value="#book")
public boolean update(Book book) {
    return bookDao.updateById(book) > 0;
}
// 删除缓存
@CacheInvalidate(name="book_",key = "#id")
public boolean delete(Integer id) {
    return bookDao.deleteById(id) > 0;
}
// 定时刷新缓存
@Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 5)
public Book getById(Integer id) {
    return bookDao.selectById(id);
}

数据报表

jetcache还提供有简单的数据报表功能,帮助开发者快速查看缓存命中信息,只需要添加一个配置即可

yaml
jetcache:
  statIntervalMinutes: 1

设置后,每1分钟在控制台输出缓存数据命中信息

9.6 整合j2cache缓存

j2cache是可以随意搭配缓存解决方案的缓存整合框架,以Ehcache与redis整合为例: 依赖 j2cache的starter中默认包含了redis坐标,官方推荐使用redis作为二级缓存,因此此处无需导入redis坐标

xml
<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
</dependency>
<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-spring-boot2-starter</artifactId>
    <version>2.8.0-release</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

配置 配置一级与二级缓存,并配置一二级缓存间数据传递方式,配置书写在名称为j2cache.properties的文件中。如果使用ehcache还需要单独添加ehcache的配置文件

1级供应商选择ehcache,供应商名称仅仅是一个ehcache,但是2级供应商选择redis时要写专用的Spring整合Redis的供应商类名SpringRedisProvider,而且这个名称并不是所有的redis包中能提供的,也不是spring包中提供的。因此配置j2cache必须参照官方文档配置,而且还要去找专用的整合包,导入对应坐标才可以使用。

一级与二级缓存最重要的一个配置就是两者之间的数据沟通方式,此类配置也不是随意配置的,并且不同的缓存解决方案提供的数据沟通方式差异化很大,需要查询官方文档进行设置。

properties
# 1级缓存


<NolebasePageProperties />




j2cache.L1.provider_class = ehcache
ehcache.configXml = ehcache.xml

# 2级缓存
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section = redis
redis.hosts = localhost:6379

# 1级缓存中的数据如何到达二级缓存
j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy

使用 j2cache的使用和jetcache比较类似,但是无需开启使用的开关,直接定义缓存对象即可使用,缓存对象名CacheChannel。

配置是j2cache的核心,相关可查阅j2cache-core核心包中的j2cache.properties文件中的说明。

java
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    @Autowired
    private CodeUtils codeUtils;

    @Autowired
    private CacheChannel cacheChannel;

    public String sendCodeToSMS(String tele) {
        String code = codeUtils.generator(tele);
        cacheChannel.set("sms",tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
        String code = cacheChannel.get("sms",smsCode.getTele()).asString();
        return smsCode.getCode().equals(code);
    }
}

10. 定时任务

10.1 Scheduled定时任务调度

Spring3.0 以后自带; pom添加坐标

xml
<!-- 添加 Scheduled 坐标 --> 
<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-context-support</artifactId> 
</dependency>

配置

yaml
spring:
  task:
   	scheduling:
      pool:
       	size: 1							# 任务调度线程池大小 默认 1
      thread-name-prefix: ssm_      	# 调度线程名称前缀 默认 scheduling-      
        shutdown:
          await-termination: false		# 线程池关闭时等待所有任务完成
          await-termination-period: 10s	# 调度线程关闭前最大等待时间,确保最后一定关闭

编写定时任务

java
/*** Scheduled 定时任务 ***/ 
@Component 
public class ScheduledDemo { 
/*** 定时任务方法 
* @Scheduled:设置定时任务 
* cron 属性:cron 表达式。定时任务触发是时间的一个字符串表达形式 
*/
	@Scheduled(cron="0/2 * * * * ?") 
	public void scheduledMethod(){
		System.out.println("定时器被触发"+new Date()); 
	} 
}

在启动类上添加 @EnableScheduling注解

10.2 Quartz 定时任务框架

基本使用

依赖

xml
<!-- Quartz 坐标 -->
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz</artifactId> 
    <version>2.2.1</version>
</dependency>

创建任务类

java
/*** 定义任务类 ***/
public class QuartzDemo implements Job {
    /*** 任务被触发时所执行的方法 */
    public void execute(JobExecutionContext arg0) throws JobExecutionException { 
        System.out.println("Execute...."+new Date()); 
    }
}

任务调度

java
public class QuartzMain { 
    public static void main(String[] args) throws Exception { 
        // 1.创建 Job 对象:你要做什么事? 
        JobDetail job = JobBuilder.newJob(QuartzDemo.class).build(); 
        /*** 简单的 trigger 触发时间:通过 Quartz 提供一个方法来完成简单的重复 调用 cron 
        * Trigger:按照 Cron 的表达式来给定触发的时间 
        */ 
        // 2.创建 Trigger 对象:在什么时间做? /*Trigger trigger =
TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSe condlyForever()) .build();*/ 
    Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedu le("0/2 * * * * ?")).build();
        // 3.创建 Scheduler 对象:在什么时间做什么事? 
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job, trigger);
        //启动
        scheduler.start();
    }
}

Springboot整合

依赖

xml
<!-- Quartz 坐标 --> 
<dependency> 
    <groupId>org.quartz-scheduler</groupId> 
    <artifactId>quartz</artifactId> 
    <version>2.2.1</version> 
    <exclusions>
        <exclusion> 
            <artifactId>slf4j-api</artifactId> 
            <groupId>org.slf4j</groupId>
        </exclusion> 
    </exclusions>
</dependency>

配置类

java
/*** Quartz 配置类 ***/
@Configuration 
public class QuartzConfig { 
    /*** 1.创建 Job 对象 */ 
    @Bean 
    public JobDetailFactoryBean jobDetailFactoryBean(){
        JobDetailFactoryBean factory = new JobDetailFactoryBean(); 
        //关联我们自己的 Job 类 
        factory.setJobClass(QuartzDemo.class); 
        return factory; 
    }
    /*** 2.创建 Trigger 对象 * 简单的 Trigger */ 
    @Bean 
    public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        SimpleTriggerFactoryBean factory = new SimpleTriggerFactoryBean(); 
        //关联 JobDetail 对象
        factory.setJobDetail(jobDetailFactoryBean.getObject()); 
        //该参数表示一个执行的毫秒数 
        factory.setRepeatInterval(2000);
        //重复次数 
        factory.setRepeatCount(5); return factory; 
    }
    
    /*** Cron Trigger */ 
    @Bean 
    public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        CronTriggerFactoryBean factory = new CronTriggerFactoryBean(); 
        factory.setJobDetail(jobDetailFactoryBean.getObject()); 
        //设置触发时间 
        factory.setCronExpression("0/2 * * * * ?"); return factory; 
    }
/*** 3.创建 Scheduler 对象 */ 
    @Bean 
    public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){ 
        SchedulerFactoryBean factory = new SchedulerFactoryBean(); 
        //关联 trigger 
        factory.setTriggers(simpleTriggerFactoryBean.getObject()); 
        return factory;
    } 
}

启动类添加 @EnableScheduling 注解 添加配置类解决job注入问题

java
@Component("myAdaptableJobFactory") 
public class MyAdaptableJobFactory extends AdaptableJobFactory {
    //AutowireCapableBeanFactory 可以将一个对象添加到 SpringIOC 容器中, 并且完成该对象注入 
    @Autowired 
    private AutowireCapableBeanFactory autowireCapableBeanFactory; 
    /*** 该方法需要将实例化的任务对象手动的添加到 springIOC 容器中并且完成对 象的注入 */ 
    @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { 
        Object obj = super.createJobInstance(bundle); 
        //将 obj 对象添加 Spring IOC 容器中,并完成注入 
        this.autowireCapableBeanFactory.autowireBean(obj); 
        return obj;
    } 
}

11. 整合数据层

11.1 整合Mybatis

依赖

xml
<!--mybatis起步依赖-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- MySQL连接驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

配置

properties
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#spring集成Mybatis环境
#pojo别名扫描包
mybatis.type-aliases-package=com.itheima.domain
#加载Mybatis映射文件
mybatis.mapper-locations=classpath:mapper/*Mapper.xml

创建实体类

java
public class User {
    // 主键
    private Long id;
    // 用户名
    private String username;
    //此处省略getter和setter方法 .. ..
    
}

编写Mapper 注意: @Mapper标记该类是一个mybatis的mapper接口,可以被spring boot自动扫描到spring上下文中

java
@Mapper
public interface UserMapper {
	public List<User> queryUserList();
}

配置Mapper映射文件 在src\main\resources\mapper路径下加入UserMapper.xml配置文件

xml
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.mapper.UserMapper">
    <select id="queryUserList" resultType="user">
        select * from user
    </select>
</mapper>

测试

java
@Controller
public class MapperController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/queryUser")
    @ResponseBody
    public List<User> queryUser(){
        List<User> users = userMapper.queryUserList();
        return users;
    }

}

11.2 整合Spring Data JPA

依赖

xml
<!-- springBoot JPA的起步依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL连接驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdk9需要导入如下坐标-->
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>

配置

properties
#DB Configuration:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

#JPA Configuration:
spring.jpa.database=MySQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy

实体类

java
@Entity
public class User {
    // 主键
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // 用户名
    private String username;
 
    //此处省略setter和getter方法... ...
}

编写UserRepository

java
public interface UserRepository extends JpaRepository<User,Long>{
    public List<User> findAll();
}

测试类

java
@RunWith(SpringRunner.class)
@SpringBootTest(classes=MySpringBootApplication.class)
public class JpaTest {
    @Autowired
    private UserRepository userRepository;
    @Test
    public void test(){
        List<User> users = userRepository.findAll();
        System.out.println(users);
    }

}

11.3 数据源技术

目前使用的数据源技术是druid,不配置druid数据源时,使用的是sptingboot内置的三种数据源技术

  • HikariCP 是springboot官方推荐的数据源技术,作为默认内置数据源使用。(不进行配置时,使用的是它)

  • Tomcat提供DataSource 如果不想用HikartCP,并且使用tomcat作为web服务器进行web程序的开发,可以使用这个,使用时需要将HikartCP技术的坐标排除掉。

  • Commons DBCP 既不使用HikartCP也不使用tomcat的DataSource时,使用当前技术。


各数据源技术配置方式:

  • Druid
yaml
spring:
  datasource:
    druid:	
   	  url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root
  • HikariCP
yaml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    hikari: # hikari节点可选,当存在hikari独立配置时,需添加。
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: root
      maximum-pool-size: 50

11.4 内置JdbcTemplate

内置JdbcTemplate解决方案。JdbcTemplate,是由spring提供进行数据层的开发的。 依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency

配置

yaml
spring:
  jdbc:
    template:
      query-timeout: -1   # 查询超时时间
      max-rows: 500       # 最大行数
      fetch-size: -1      # 缓存行数

使用示例

java
public class JdbcTemplateDemo2 {
			
    //Junit单元测试,可以让方法独立执行
    //1. 获取JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    /**
	* 1. 修改1号数据的 salary 为 10000
	*/
    @Test
    public void test1(){
        //2. 定义sql
        String sql = "update emp set salary = 10000 where id = 1001";
        //3. 执行sql
        int count = template.update(sql);
        System.out.println(count);
    }
			
    /**
	* 2. 添加一条记录
	*/
    @Test
    public void test2(){
        String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
        int count = template.update(sql, 1015, "郭靖", 10);
        System.out.println(count);

    }
			
    /**
	* 3.删除刚才添加的记录
	*/
    @Test
    public void test3(){
        String sql = "delete from emp where id = ?";
        int count = template.update(sql, 1015);
        System.out.println(count);
    }

    /**
	* 4.查询id为1001的记录,将其封装为Map集合
	* 注意:这个方法查询的结果集长度只能是1
	*/
    @Test
    public void test4(){
        String sql = "select * from emp where id = ? or id = ?";
        Map<String, Object> map = template.queryForMap(sql, 1001,1002);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}

    }
			
    /**
			     * 5. 查询所有记录,将其封装为List
			     */
    @Test
    public void test5(){
        String sql = "select * from emp";
        List<Map<String, Object>> list = template.queryForList(sql);

        for (Map<String, Object> stringObjectMap : list) {
            System.out.println(stringObjectMap);
        }
    }

    /**
	* 6. 查询所有记录,将其封装为Emp对象的List集合
	*/

    @Test
    public void test6(){
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {

            @Override
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp = new Emp();
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");

                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                return emp;
            }
        });
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
	* 6. 查询所有记录,将其封装为Emp对象的List集合
	*/

    @Test
    public void test6_2(){
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
	* 7. 查询总记录数
	*/

    @Test
    public void test7(){
        String sql = "select count(id) from emp";
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);
    }

}

11.5 数据库技术

springboot提供了3款内置的数据库,分别是

  • H2
  • HSQL
  • Derby

这三款数据库底层都是使用java语言开发的。可以采用内嵌的形式运行在spirngboot容器中。 在开发过程中,如果需要测试使用,无需存储时,可以使用这些运行在内存中的数据库。

以H2为例

依赖

xml
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

配置

java
spring:
  h2:
    console:
      enabled: true
      path: /h2
  datasource:
    url: jdbc:h2:~/test
    hikari:
      driver-class-name: org.h2.Driver
      username: sa
      password: 123456

web端访问路径/h2,访问密码123456。

12. 邮件

发邮件是java程序的基本操作,springboot整合javamail其实就是简化开发。

邮件相关概念:

  • SMTP(Simple Mail Transfer Protocol):简单邮件传输协议,用于发送电子邮件的传输协议
  • POP3(Post Office Protocol - Version 3):用于接收电子邮件的标准协议
  • IMAP(Internet Mail Access Protocol):互联网消息协议,是POP3的替代协议

SMPT是发邮件的标准,POP3是收邮件的标准,IMAP是对POP3的升级。

12.1 内置邮件

依赖

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

配置

yaml
spring:
  mail:
    host: smtp.126.com
    username: test@126.com
    password: test

java程序仅用于发送邮件,邮件的功能还是邮件供应商提供的,所以这里是用别人的邮件服务,要配置对应信息。 host配置的是提供邮件服务的主机协议,当前程序仅用于发送邮件,因此配置的是smtp的协议。 password并不是邮箱账号的登录密码,是邮件供应商提供的一个加密后的密码

发送邮件

java
@Service
public class SendMailServiceImpl implements SendMailService {
    @Autowired
    private JavaMailSender javaMailSender;

    //发送人
    private String from = "test@qq.com";
    //接收人
    private String to = "test@126.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "测试邮件正文内容";

    @Override
    public void sendMail() {
        // 将发送邮件的必要信息(发件人、收件人、标题、正文)封装到SimpleMailMessage对象中,可以根据规则设置发送人昵称等。
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from+"(小甜甜)");
        message.setTo(to);
        message.setSubject(subject);
        message.setText(context);
        javaMailSender.send(message);
    }
}

发送网页正文邮件

java
@Service
public class SendMailServiceImpl2 implements SendMailService {
    @Autowired
    private JavaMailSender javaMailSender;

    //发送人
    private String from = "test@qq.com";
    //接收人
    private String to = "test@126.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "<img src='ABC.JPG'/><a href='https://www.itcast.cn'>点开有惊喜</a>";

    public void sendMail() {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message);
            helper.setFrom(to+"(小甜甜)");
            helper.setTo(from);
            helper.setSubject(subject);
            helper.setText(context,true);		//此处设置正文支持html解析

            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

发送带有附件的邮件

java
@Service
public class SendMailServiceImpl2 implements SendMailService {
    @Autowired
    private JavaMailSender javaMailSender;

    //发送人
    private String from = "test@qq.com";
    //接收人
    private String to = "test@126.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "测试邮件正文";

    public void sendMail() {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message,true);		//此处设置支持附件
            helper.setFrom(to+"(小甜甜)");
            helper.setTo(from);
            helper.setSubject(subject);
            helper.setText(context);

            //添加附件
            File f1 = new File("springboot_23_mail-0.0.1-SNAPSHOT.jar");
            File f2 = new File("resources\\logo.png");

            helper.addAttachment(f1.getName(),f1);
            helper.addAttachment("最靠谱的培训结构.png",f2);

            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}